iT邦幫忙

2026 iThome 鐵人賽

DAY 25
0
Software Development

從零開始將作品整理成GitHub履歷系列 第 25 篇

Day25|遇到Merge Conflict了! 它是誰?

  • 分享至 

  • xImage
  •  

昨天使用了git merge將readme-update的修改合併回master,而且Git還自動幫我完成了Fast-forward,過程都十分順利!
但是我突然想到,如果我跟同學一起開發專案然後各自在不同的Branch修改功能,卻又剛好修改到同一個地方,那 Git到底會保留誰的版本呢?
這個情況有可能就是遇到**Merge Conflict(合併衝突)**了,那它是誰勒我們今天就來認識吧!


Merge Conflict 是什麼?

Merge Conflict 叫做合併衝突。
當我們使用git merge 合併不同 Branch時,如果兩條分支對同一個地方做了不同的修改,Git可能就無法自動判斷該保留哪個版本,這時候就會發生Merge Conflict。

但是發生衝突並不是代表Git壞掉了,只是Git會需要我們自己手動確認要保留哪些內容才能繼續完成合併。今天我也會簡單的用我的eyes_prj製造一個Merge Conflict,實際看看Git會出現什麼反應,然後我該怎麼解決。

實作 Merge Conflict

首先一樣使用 git status,確認目前所在的 Branch是,而且沒有尚未提交的修改就可以開始了。

1. 建立測試Merge Conflict的分支

我要先建立一條分支然後命名為conflict-test ,我將用它來練習 Merge Conflict。
先在PowerShell 輸入:

git switch -c conflict-test

它跟昨天我們建立Branch的指令差在於昨天是將建立分支和切換分開兩個步驟進行。
這個指令的-c 就是 --create,意思是建立新分支,所以這個指令才可以同時完成建立新的Branch跟切換到那個分支。

2. 建立Merge Conflict的測試檔案

接下來建立一個測試用的文字檔案,等等就用它來製造 Merge Conflict。
先在 PowerShell 輸入:notepad conflict-demo.txt
這個指令會用記事本開啟 conflict-demo.txt,如果檔案還不存在就可以建立新檔案。
然後打一些內容,我是輸入:

專案名稱:眼科病人與術前醫囑管理系統
專案狀態:開發中

儲存後將檔案加入暫存區接著建立 Commit
https://ithelp.ithome.com.tw/upload/images/20261009/20178158Ej8cnkKqkW.png
這樣就成功在conflict-test 記錄了測試檔案的初始版本了。

3. 讓 master 也擁有測試檔案

但是現在只有 conflict-test 有這筆新的Commit,master 還沒有,為了讓兩條 Branch 能夠修改到同一個檔案所以我要先讓它們擁有共同的初始版本。
先切換分支到master,接著輸入:git merge conflict-test
https://ithelp.ithome.com.tw/upload/images/20261009/20178158bmkPvbBWrR.png
這次又出現了 Fast-forward,因為現在master 沒有其他新的修改,所以Git可以直接將 conflict-test的Commit 合併進來。這樣我們就讓master和conflict-test都有相同的conflict-demo.txt可以開始製造衝突了!

4. 在 master 修改測試檔案

先在 master 開啟測試檔案,
把原本的:專案狀態:開發中
修改成: 專案狀態:已完成開發
接著建立 Commit,這樣master 就有自己的修改版本了
https://ithelp.ithome.com.tw/upload/images/20261009/20178158fMjGfNzW92.png

5. 在 conflict-test 修改同一行

如果我們沒有修改conflict-test的conflict-demo.txt的話Git就會覺得這是上一個版本並不是兩邊出現不同,就不會有Merge Conflict發生。
所以接下來切換回 conflict-test修改conflict-demo.txt,把專案狀態改成持續維護中,接著一樣建立Commit。
https://ithelp.ithome.com.tw/upload/images/20261009/20178158926kgzEiLH.png

接下來就要看看當我把兩條Branch 合併時,Git 會發生什麼事

6. 執行 Merge遇到衝突

現在兩條 Branch 都已經修改了同一個檔案,而且修改的內容不同接下來就要實際合併看看!

首先切換回master接著輸入:

git merge conflict-test

這時候,PowerShell 出現了Merge Conflict 了:
https://ithelp.ithome.com.tw/upload/images/20261009/201781583a3zTWeSFY.png
CONFLICT (content)表示 Git 發現檔案內容有衝突。
Automatic merge failed 表示 Git 無法自動完成這次合併。
所以Git 暫時停止了合併,需要等待我們手動解決衝突。

7. 查看 Merge Conflict 的內容

接著我們打開發生衝突的那個澈士檔案看看它現在長什麼樣子:
https://ithelp.ithome.com.tw/upload/images/20261009/20178158QRHJxlkjFB.png
發現居然多出了幾個奇怪的符號,問了AI才知道這些符號是 Git 用來標示衝突位置的:

 <<<<<<< HEAD:代表目前所在的 master 版本。
 =======:用來分隔兩邊不同的修改內容。
 >>>>>>> conflict-test:代表準備合併進來的 conflict-test 版本。

Git把兩個版本都顯示出來了讓我們自己決定要保留哪一個或是重新整理成想要的內容。

手動解決 Merge Conflict

這次我決定保留 conflict-test 的版本,也就是「持續維護中」。
所以我將其他不需要的內容和 Git 產生的衝突標記刪除,讓檔案:

專案名稱:眼科病人與術前醫囑管理系統
專案狀態:持續維護中

接著回到PowerShell,輸入:

git add conflict-demo.txt
git status

https://ithelp.ithome.com.tw/upload/images/20261009/20178158b0JxoEtI9s.png
All conflicts fixed but you are still merging.表示衝突已經解決但合併程序還沒有正式完成。

最後輸入:

git commit -m "Resolve merge conflict"

這樣就成功建立 Merge Commit,完成這次的合併了!

查看合併後的 Git 紀錄

git log --oneline --graph --decorate -8

完成 Merge Conflict 後,我想看看這次的合併有沒有成功記錄下來,所以在 PowerShell 輸入:

git log --oneline --graph --decorate -8

這個指令可以讓我們用比較簡單的方式查看 Git 的 Commit 紀錄:

--oneline:將每筆 Commit 簡化成一行。
--graph:使用線條顯示 Branch 的分支與合併關係。
--decorate:顯示 Branch 名稱及 HEAD 等標記。
-8:只顯示最近 8 筆 Commit。

https://ithelp.ithome.com.tw/upload/images/20261009/20178158D30EB2SEAO.png
跟昨天的 Fast-forward 不同這次的紀錄出現了分岔的線條!

可以看到 master 和 conflict-test 從共同的Commit開始,各自進行修改最後再透過 91955b9 Resolve merge conflict 合併在一起。
原來Merge Commit不只記錄了合併結果,也保留了兩條Branch各自修改的歷史,讓我們可以清楚看到整個的合併過程。


因為今天只是練習Merge Conflict,但我不想影響原本的專案所以我先使用 git branch merge-conflict-practice 建立一條新的 Branch用來保存今天的練習紀錄。接著使用 git reset --hard origin/master,讓 master 回到 GitHub 上的正式版本。
那麼今天成功的製造並解決了第一次的Merge Conflict,也了解原來發生衝突並不是 Git 出錯,是需要我們手動去確認要保留哪些修改,也學會了如何保存練習紀錄,並避免影響原本的專案!


上一篇
Day24|認識Git Merge:把 Branch 合併回 master
系列文
從零開始將作品整理成GitHub履歷 共 25 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言